package jssia.database.mysql.columns;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class BitColumn extends Column {

    private final int maxBits;

    public BitColumn(int maxBits) {
        this.maxBits = maxBits;
    }

    public byte[] get(ResultSet rs) throws SQLException {
        return rs.getBytes(name);
    }

    public byte getByte(ResultSet rs) throws SQLException {
        if (maxBits > 8)
            throw new IllegalStateException("This column supports more than one byte (" + maxBits + " bits), " +
                    "you probably should get all of the bytes instead.");

        return rs.getByte(name);
    }
    public int getInt(ResultSet rs) throws SQLException {
        final byte[] bytes = rs.getBytes(name);
        return bytes == null ? 0 : byteArrayToInt(bytes);
    }

    public boolean getBool(ResultSet rs) throws SQLException {
        if (maxBits != 1)
            throw new IllegalStateException("Bit columns only support boolean operations if the length of the column is defined as 1."
                    + "  Currently the column is defined with a length of " + maxBits);

        return rs.getBoolean(name);
    }

    public void set(PreparedStatement ps, int index, byte[] bytes) throws SQLException {
        if (bytes.length > 8)
            throw new IllegalArgumentException("Invalid byte array length of " + bytes.length
                    + ", cannot be more than 8.");

        ps.setBytes(index, bytes);
    }

    public void set(PreparedStatement ps, int index, int value) throws SQLException {
        ps.setInt(index, value);
    }

    public void set(PreparedStatement ps, int index, boolean flag) throws SQLException {
        ps.setBoolean(index, flag);
    }

    private static int byteArrayToInt(byte[] bytes) {
        if (bytes.length != 8)
            throw new IllegalArgumentException("Illegal array length of " + bytes.length + ", must contain 8 bytes.");

        return ((bytes[4] & 0xFF) << 24)
            + ((bytes[5] & 0xFF) << 16)
            + ((bytes[6] & 0xFF) << 8)
            + (bytes[7] & 0xFF);
    }
}
